package com.redis.redisson;

import org.redisson.Redisson;
import org.redisson.RedissonRedLock;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author liyanhao
 * @Date 2023-02-14 1:48
 */
@RestController
public class StockController {
    //分布式锁
    @Autowired
    private Redisson redisson;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @RequestMapping("deduct_stock")
    public String duductStock(){
        String lockkey = "lock:product_102";
        //stringRedisTemplate.opsForValue().setIfAbsent(lockkey, "zhangsan");
        //stringRedisTemplate.expire(lockkey, 10, TimeUnit.SECONDS);
        String clientId = UUID.randomUUID().toString();
        //jedis.setnx(k,v)
        Boolean result = stringRedisTemplate.opsForValue().setIfAbsent(lockkey, clientId, 30, TimeUnit.SECONDS);
        if (!result) {
            return "errot_code";
        }
        //获取锁对象
        RLock redissonLock = redisson.getLock(lockkey);
        //加分布式锁
        redissonLock.lock();
        try {
            int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));
            if (stock > 0) {
                int realStock = stock - 1;
                stringRedisTemplate.opsForValue().set("stock",realStock+"");
                System.out.println("扣减成功，剩余库存：" + realStock);
            }else {
                System.out.println("扣减失败 库存不足");
            }
        }finally {
            if (clientId.equals(stringRedisTemplate.opsForValue().get(lockkey))) {
                stringRedisTemplate.delete(lockkey);
            }
            //解锁
            redissonLock.unlock();
        }
        return "end";

    }

    @RequestMapping("/readlock")
    public String redlock() {
        String lockkey = "product_001";
        //这里需要自己实例化不同的redis实例的redisson客户端连接，
        //此处进行简化了
        RLock redissonLock = redisson.getLock(lockkey);
        RLock redissonLock1 = redisson.getLock(lockkey);
        RLock redissonLock2 = redisson.getLock(lockkey);
        //根据多个rLock对象构建RedissonRedLock 最核心的差别就在这里
        RedissonRedLock redLock = new RedissonRedLock(redissonLock1, redissonLock2, redissonLock);
        try {
            //waitTimeout 尝试获取锁的最大等待时间 超过这个值 则认为获取锁失败
            // leaseTime 锁的持有时间 超过这个时间锁会自动失效
            // 值应设置为大于业务处理的时间 确保在锁有效期内业务能处理完成
            boolean res = redLock.tryLock(10, 30, TimeUnit.SECONDS);
            if (res) {
                //成功获得锁 在这里处理业务
            }

        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }finally {
            redLock.unlock();
        }
        return "end";
    }
}





















